Messaging with RabbitMQ

Messaging with RabbitMQ

本文翻译自:https://spring.io/guides/gs/messaging-rabbitmq/
打算翻译一批Spring的各种指引文档,此为第一篇

本指南将引导您完成建立一个发布和订阅消息的RabbitMQ AMQP服务器的过程。

What you’ll build

您将使用Spring AMQP的RabbitTemplate构建一个发布消息的应用程序,并使用MessageListenerAdapter订阅POJO上的消息。

What you’ll need

  • 约15分钟
  • 最喜欢的文本编辑器或IDE
  • JDK 1.8或更高版本
  • Gradle 2.3+Maven 3.0+
  • 您也可以从本指南导入代码,以及直接在Spring Tool Suite(STS)中查看网页,并从那里开始工作 。
  • RabbitMQ服务器(安装说明如下)

    How to complete this guide

与大多数Spring 入门指南一样,您可以从头开始并完成每个步骤,也可以绕过已经熟悉的基本设置步骤。 无论如何,你最终得到工作代码。

要从头开始**,请转到使用Gradle构建

要跳过基本操作**,请执行以下操作:

  • 下载并解压缩本指南的源代码仓库,或使用Gitgit clone https:// github.com / spring-guides / gs-messaging-rabbitmq.git
  • cd到gs-messaging-rabbitmq / initial
  • 跳转到创建RabbitMQ消息接收器

完成后,您可以根据gs-messaging-rabbitmq / complete中的代码检查结果。

Build with Gradle

Build with Maven

Build with your IDE

Set up RabbitMQ broker

在构建消息传递应用程序之前,您需要设置将处理接收和发送消息的服务器。

RabbitMQ是一个AMQP服务器。 服务器可以免费访问[http://www.rabbitmq.com/download.html"(http://www.rabbitmq.com/download.html)。 你可以手动下载,或者如果你使用Mac与homebrew:

1
brew install rabbitmq

解压缩服务器并使用默认设置启动它。

1
rabbitmq-server

你应该会看到这样的:

1
2
3
4
5
6
7
            RabbitMQ 3.1.3. Copyright (C) 2007-2013 VMware, Inc.
## ## Licensed under the MPL. See http://www.rabbitmq.com/
## ##
########## Logs: /usr/local/var/log/rabbitmq/rabbit@localhost.log
###### ## /usr/local/var/log/rabbitmq/rabbit@localhost-sasl.log
##########
Starting broker... completed with 6 plugins.

如果Docker在本地运行,您还可以使用[Docker Compose](https://docs.docker.com/compose/)快速启动RabbitMQ服务器。 在Github的“完整”项目的根目录中有一个docker-compose.yml。 很简单:

docker-compose.yml

1
2
3
4
5
rabbitmq:
image: rabbitmq:management
ports:
- "5672:5672"
- "15672:15672"

有了这个文件在当前目录中,你可以运行docker-compose up来使RabbitMQ在容器中运行

Create a RabbitMQ message receiver

对于任何基于消息的应用程序,您需要创建一个接收器来响应已发布的消息。

src/main/java/hello/Receiver.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package hello;

import java.util.concurrent.CountDownLatch;
import org.springframework.stereotype.Component;

@Component
public class Receiver {

private CountDownLatch latch = new CountDownLatch(1);

public void receiveMessage(String message) {
System.out.println("Received <" + message + ">");
latch.countDown();
}

public CountDownLatch getLatch() {
return latch;
}

}

`Receiver’是一个简单的POJO,它定义了一个接收消息的方法。 当您注册它以接收消息时,您可以将其命名为任何您想要的。

** 为了方便起见,这个POJO也有一个CountDownLatch。 这允许它发信号通知接收到消息。 这是你不可能在生产应用程序中实现的东西。

Register the listener and send a message

Spring AMQP的`RabbitTemplate’提供了使用RabbitMQ发送和接收消息所需的一切。 具体来说,您需要配置:

  • 消息侦听器容器
  • 声明队列,交换和它们之间的绑定
  • 发送一些消息以测试侦听器的组件
** Spring Boot自动创建一个连接工厂和一个RabbitTemplate,减少了你必须编写的代码量。

你将使用RabbitTemplate来发送消息,你将使用消息监听器容器注册一个Receiver来接收消息。 连接工厂并驱动两者,允许它们连接到RabbitMQ服务器。

src/main/java/hello/Application.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
package hello;

import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.TopicExchange;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.amqp.rabbit.listener.adapter.MessageListenerAdapter;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
public class Application {

final static String queueName = "spring-boot";

@Bean
Queue queue() {
return new Queue(queueName, false);
}

@Bean
TopicExchange exchange() {
return new TopicExchange("spring-boot-exchange");
}

@Bean
Binding binding(Queue queue, TopicExchange exchange) {
return BindingBuilder.bind(queue).to(exchange).with(queueName);
}

@Bean
SimpleMessageListenerContainer container(ConnectionFactory connectionFactory,
MessageListenerAdapter listenerAdapter) {
SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
container.setQueueNames(queueName);
container.setMessageListener(listenerAdapter);
return container;
}

@Bean
MessageListenerAdapter listenerAdapter(Receiver receiver) {
return new MessageListenerAdapter(receiver, "receiveMessage");
}

public static void main(String[] args) throws InterruptedException {
SpringApplication.run(Application.class, args);
}

}

@ SpringBootApplication是一个方便的注解,添加了以下所有内容:

  • @ Configuration将类标记为应用程序上下文的bean定义的来源。
  • @ EnableAutoConfiguration告诉Spring Boot根据类路径设置,其他bean和各种属性设置开始添加bean。
  • 通常你会为Spring MVC应用程序添加@ EnableWebMvc,但是Spring Boot在类路径上看到 spring-webmvc 时会自动添加它。这将应用程序标记为Web应用程序,并激活关键行为,如设置一个“DispatcherServlet”。
  • @ ComponentScan告诉Spring在hello包中寻找其他组件,配置和服务,允许它找到控制器。

main()方法使用Spring Boot的SpringApplication.run()方法来启动应用程序。你有注意到一行XML?没有 web.xml 文件。这个Web应用程序是100%纯Java,你不必处理配置任何管道或基础设施。

listenerAdapter()方法中定义的bean被注册为在container()中定义的容器中的消息侦听器。它将监听“spring-boot”队列上的消息。因为Receiver类是一个POJO,它需要被包装在MessageListenerAdapter中,你可以指定它来调用receiveMessage

** JMS队列和AMQP队列具有不同的语义。 例如,JMS仅向一个使用者发送排队的消息。 虽然AMQP队列做同样的事情,AMQP生产者不直接发送消息到队列。 相反,消息发送到交换,可以转到单个队列,或扇出到多个队列(1->1,1->n),模拟JMS主题的概念。 更多,见Understanding AMQP.

消息侦听器容器和receiver beans都是您侦听消息所需要的。 要发送消息,您还需要一个Rabbit模板。

queue()方法创建一个AMQP队列。 exchange()方法创建一个主题交换。 binding()方法将这两个绑定在一起,定义当RabbitTemplate发布到交换时发生的行为。

** Spring AMQP要求将“Queue”,“TopicExchange”和“Binding”声明为顶级Spring bean,以便正确设置。

Send a Test Message

测试消息由CommandLineRunner发送,它也等待接收器中的锁存器(此处原文: the latch in the receiver )并关闭应用程序上下文:

src/main/java/hello/Runner.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package hello;

import java.util.concurrent.TimeUnit;

import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.stereotype.Component;

@Component
public class Runner implements CommandLineRunner {

private final RabbitTemplate rabbitTemplate;
private final Receiver receiver;
private final ConfigurableApplicationContext context;

public Runner(Receiver receiver, RabbitTemplate rabbitTemplate,
ConfigurableApplicationContext context) {
this.receiver = receiver;
this.rabbitTemplate = rabbitTemplate;
this.context = context;
}

@Override
public void run(String... args) throws Exception {
System.out.println("Sending message...");
rabbitTemplate.convertAndSend(Application.queueName, "Hello from RabbitMQ!");
receiver.getLatch().await(10000, TimeUnit.MILLISECONDS);
context.close();
}

}

The runner可以在测试中模拟出来,以便接收器可以单独测试。

Run the Application

main()方法通过创建一个Spring应用程序上下文来启动这个过程。 这将启动消息侦听容器,它将开始侦听消息。 有一个Runner bean然后自动执行:它从应用程序上下文中检索RabbitTemplate,并发送一个“RabbitMQ!”。 消息在“spring-boot”队列。 最后,它关闭Spring应用程序上下文,应用程序结束。

Build an executable JAR

您可以使用Gradle或Maven从命令行运行应用程序。 或者,您可以构建单个可执行文件,其中包含所有必需的依赖关系,类和资源,并运行它。 这使得在整个开发生命周期中,跨不同环境等等,易于将服务作为应用程序进行发布,版本和部署。

如果您使用Gradle,可以使用./gradlew bootRun运行应用程序。 或者你可以使用./gradlew build来构建JAR文件。 然后可以运行JAR文件:

1
java -jar build/libs/gs-messaging-rabbitmq-0.1.0.jar

如果您使用Maven,可以使用./maven spring-boot:run运行应用程序。 或者你可以用./mvn clean package构建JAR文件。 然后可以运行JAR文件:

1
java -jar target/gs-messaging-rabbitmq-0.1.0.jar
** 上面的过程将创建一个可运行的JAR。 您也可以选择[构建传统的WAR文件](https://spring.io/guides/gs/convert-jar-to-war/)

您应该看到以下输出:

1
2
Sending message...
Received <Hello from RabbitMQ!>

Summary

恭喜! 你刚刚用Spring和RabbitMQ开发了一个简单的发布和订阅应用程序。 more you can do with Spring and RabbitMQ比这里涵盖的内容更多,但这应该提供一个好的 开始。

想要写一个新的指南或贡献现有的? 查看我们的 contribution guidelines.

您的支持将鼓励我继续创作!